
using Microsoft.Xna.Framework;
using Tama_Chan.Entities_ns;
using Tama_Chan.GameEngine_ns;
using System;


namespace Tama_Chan.PhysicsEngine_ns
{
   public class PhysicsEngine
   {
      private GameEngine GameEngine { get; set; }


      public PhysicsEngine(GameEngine gameEngine)
      {
         GameEngine = gameEngine;
      }


      public void Update(GameTime gameTime)
      {
         Rectangle gameBounds = GameEngine.Game1.GameBounds;
         Player player = GameEngine.Player;
         bool playerHasBeenTeleportedThisFrame = false;
         Mystery mystery = GameEngine.Mystery;
         PowerPellet powerPellet = GameEngine.PowerPellet;

         // =====( Begin Player Hits Mystery )=====================================================

         if(!mystery.IsDead && player.Bounds.Intersects(mystery.Bounds))
         {
            GameEngine.Score += mystery.ScoreValue;
            GameEngine.FontParticleEngine.AddFontParticle(mystery.Position, "+" + mystery.ScoreValue, Color.White, gameTime.TotalGameTime.Ticks);
            mystery.SoundOne.Play();
            mystery.Reset();
         }

         // =====( End Player Hits Mystery )=======================================================
         // ///////////////////////////////////////////////////////////////////////////////////////
         // =====( Begin Player Hits PowerPellet )=================================================

         if(powerPellet.State == PowerPelletState.Visible && player.Bounds.Intersects(powerPellet.Bounds))
         {
				powerPellet.State = PowerPelletState.Attacking;
				GameEngine.Score += powerPellet.ScoreValue;
         }

         // =====( End Player Hits PowerPellet )===================================================
         // ///////////////////////////////////////////////////////////////////////////////////////
         // =====( Begin Food GameBounds Check )===================================================

         for(int i = 0; i < GameEngine.FoodList.Count; i++ )
         {
            DoGameBoundsCheck(gameBounds, GameEngine.FoodList[i]);
         }

         // =====( End Food GameBounds Check )=====================================================
         //////////////////////////////////////////////////////////////////////////////////////////
         // =====( Begin Enemy GameBounds Check )==================================================

         if(GameEngine.PowerPellet.State == PowerPelletState.Attacking)
         {
            for(int i = 0; i < GameEngine.EnemyList.Count; i++)
            {
               DoGameBoundsCheck(gameBounds, GameEngine.EnemyList[i]);
            }
         }

         // =====( End Enemy GameBounds Check )====================================================
         //////////////////////////////////////////////////////////////////////////////////////////
         // =====( Begin Player Eats Food )========================================================

         for(int i = 0; i < GameEngine.FoodList.Count; i++)
         {
            Food food = GameEngine.FoodList[i];
            if(player.Bounds.Intersects(food.Bounds))
            {
               food.SoundOne.Play();
               GameEngine.Score += food.ScoreValue;

               if(GameEngine.Health + food.HealthValue <= 100)
               {
                  GameEngine.Health += food.HealthValue;
                  GameEngine.FontParticleEngine.AddFontParticle(food.Position + new Vector2(75f, 0f), "+" + food.HealthValue, Color.GreenYellow, gameTime.TotalGameTime.Ticks);
               }

               GameEngine.FontParticleEngine.AddFontParticle(food.Position, "+" + food.ScoreValue, Color.White, gameTime.TotalGameTime.Ticks);
               GameEngine.GameEntityList.Remove(food);
               GameEngine.FoodList.Remove(food);
               GameEngine.PowerPellet.EatenFoodCount++;

               // Create explosion
               GameEngine.ParticleEngine.CreateExplosionEffect(gameTime, player.Position, 20, 40);
            }
         }

         // =====( End Player Eats Food )==========================================================
         //////////////////////////////////////////////////////////////////////////////////////////
         // =====( Begin Player Hits Enemy )=======================================================

         for(int i = 0; i < GameEngine.EnemyList.Count; i++)
         {
            Enemy enemy = GameEngine.EnemyList[i];
            if(player.Bounds.Intersects(enemy.Bounds))
            {
               if(GameEngine.PowerPellet.State == PowerPelletState.Attacking && enemy.Color == Enemy.FleeingColor)
               {
                  /*
                   * Player eats a fleeing enemy.
                   */
                  GameEngine.Score += powerPellet.EnemyScoreValues[powerPellet.EnemiesEaten];
                  enemy.SoundOne.Play();
                  GameEngine.FontParticleEngine.AddFontParticle(player.Position, "+" + powerPellet.EnemyScoreValues[powerPellet.EnemiesEaten], Color.White, gameTime.TotalGameTime.Ticks);
                  GameEngine.ParticleEngine.CreateExplosionEffect(gameTime, player.Position, 20, 40);
                  powerPellet.EnemiesEaten++;
               }
               else
               {
                  /*
                   * Player is hit by enemy.
                   */
                  GameEngine.Health += enemy.HealthValue;
                  GameEngine.Game1.VibrateController.Start(TimeSpan.FromSeconds(.25));

                  if(GameEngine.Health <= 0)
                  {
                     // Player dies
                     GameEngine.GameState = GameState.GameOver;
                     return;
                  }

                  GameEngine.FontParticleEngine.AddFontParticle(enemy.Position, enemy.HealthValue.ToString(), Color.OrangeRed, gameTime.TotalGameTime.Ticks);

                  // Create explosion
                  player.SoundOne.Play();
                  GameEngine.ParticleEngine.CreateExpandingRingEffect(gameTime, player.Position, GameEngine.ParticleDepth);
               }

               GameEngine.GameEntityList.Remove(enemy);
               GameEngine.EnemyList.Remove(enemy);
            }
         }

         // =====( End Player Hits Enemy )=========================================================
         //////////////////////////////////////////////////////////////////////////////////////////
         // =====( Begin Player GameBounds Check )=================================================

         DoGameBoundsCheck(gameBounds, player);

         // =====( End Player GameBounds Check )===================================================
         //////////////////////////////////////////////////////////////////////////////////////////
         // =====( Begin Player Teleportion )======================================================

         for(int i=0; i<GameEngine.TeleporterList.Count; i++)
         {
            if(playerHasBeenTeleportedThisFrame)
            {
               break;
            }

            Teleporter teleporter = GameEngine.TeleporterList[i];

            if(teleporter.Bounds.Contains(player.Bounds))
            {
               if(teleporter.TeleporterCurrentState == TeleporterState.Resting)
               {
                  // Player moved in.
                  teleporter.TeleporterCurrentState = TeleporterState.Sending;
                  GameEngine.ParticleEngine.CreateTeleporterEffect(gameTime, 
                                                                   new Vector2(teleporter.Position.X + teleporter.Bounds.Width/2f, 
                                                                               teleporter.Position.Y + teleporter.Bounds.Height/2f), 
                                                                   false);
                  teleporter.TargetTeleporter.TeleporterCurrentState = TeleporterState.Receiving;
                  GameEngine.ParticleEngine.CreateTeleporterEffect(gameTime,
                                                                   new Vector2(teleporter.TargetTeleporter.Position.X + teleporter.TargetTeleporter.Bounds.Width / 2f,
                                                                               teleporter.TargetTeleporter.Position.Y + teleporter.TargetTeleporter.Bounds.Height / 2f), 
                                                                   true);
                  int x = teleporter.TargetTeleporter.Bounds.X + teleporter.TargetTeleporter.Bounds.Width / 2;
                  int y = teleporter.TargetTeleporter.Bounds.Y + teleporter.TargetTeleporter.Bounds.Height / 2;
                  player.Position = new Vector2(x, y);
                  playerHasBeenTeleportedThisFrame = true;
                  teleporter.SoundOne.Play();

               }
               else if(teleporter.TeleporterCurrentState == TeleporterState.Sending)
               {
                  // Sending player. Nothing for now.
               }
               else if(teleporter.TeleporterCurrentState == TeleporterState.Receiving)
               {
                  // Player was teleported in. Just let him sit there if he wants.
               }
            }
            else
            {
               teleporter.TeleporterCurrentState = TeleporterState.Resting;
            }
         }

         // =====( End Player Teleportion )========================================================
      }


      private static void DoGameBoundsCheck(Rectangle gameBounds, GameEntity gameEntity)
      {
         var modifiedPosition = gameEntity.Position;
         var modifiedVelocity = gameEntity.Velocity;

			// It's too far North and still heading North.
         if(gameEntity.Bounds.Top < gameBounds.Top && gameEntity.Velocity.Y < 0)
         {
            modifiedPosition.Y += gameBounds.Top - gameEntity.Bounds.Top + 1;
            if(!(gameEntity is Player))
            {
               modifiedVelocity.Y *= -1;
               gameEntity.SoundTwo.Play();
            }
         }
			// It's too far South and still heading South.
         else if(gameEntity.Bounds.Bottom > gameBounds.Bottom && gameEntity.Velocity.Y > 0)
         {
            modifiedPosition.Y += gameBounds.Bottom - gameEntity.Bounds.Bottom - 1;
            if(!(gameEntity is Player))
            {
               modifiedVelocity.Y *= -1;
               gameEntity.SoundTwo.Play();
            }
         }

			// It's too far West and still heading West.
         if(gameEntity.Bounds.Left < gameBounds.Left && gameEntity.Velocity.X < 0)
         {
            modifiedPosition.X += gameBounds.Left - gameEntity.Bounds.Left + 1;
            if(!(gameEntity is Player))
            {
               modifiedVelocity.X *= -1;
               gameEntity.SoundTwo.Play();
            }
         }
			// It's too far East and still heading East.
         else if(gameEntity.Bounds.Right > gameBounds.Right && gameEntity.Velocity.X > 0)
         {
            modifiedPosition.X += gameBounds.Right - gameEntity.Bounds.Right - 1;
            if(!(gameEntity is Player))
            {
               modifiedVelocity.X *= -1;
               gameEntity.SoundTwo.Play();
            }
         }

         gameEntity.Position = modifiedPosition;
         gameEntity.Velocity = modifiedVelocity;
      }

   }
}
